iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0

嗨我是k66,承上篇實作OinkBL.c,因最初前兩篇的寫法會遇到出現Bmp顏色、位置出現異常,故當時改成今日的做法—ConvertBmpToBlt()後終於能正常顯示Logo.bmp!程式碼連結

https://ithelp.ithome.com.tw/upload/images/20230923/20161828RbV9sCoCec.png


本篇與前篇做出區別,介紹ConvertBmpToBlt()這個自訂義function,僅需紀錄記憶體位置(起始處及BufferSize,以推估終點處),就可以將Bmp轉至Blt。

EFI_STATUS ConvertBmpToBlt(VOID *BmpImage, UINTN BmpImageSize, VOID **GopBlt, UINTN *GopBltSize, UINTN *PixelHeight, UINTN *PixelWidth)
{

	UINT8                         *ImageData;
	UINT8                         *ImageBegin;
	BMP_IMAGE_HEADER              *BmpHeader;
	EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;
	EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
	UINT64                        BltBufferSize;
	UINTN                         Height;
	UINTN                         Width;
	UINTN                         ImageIndex;

	BmpHeader = (BMP_IMAGE_HEADER *)BmpImage;
	ImageBegin = ((UINT8 *)BmpImage) + BmpHeader->ImageOffset;
    
    /* Bmp僅支援24位元或32位元,非者即非Bmp */
	if (BmpHeader->BitPerPixel != 24 && BmpHeader->BitPerPixel != 32)
		return EFI_UNSUPPORTED;

	BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
	*GopBltSize = (UINTN)BltBufferSize;
	*GopBlt = AllocatePool(*GopBltSize);   
	
	*PixelWidth = BmpHeader->PixelWidth;
	*PixelHeight = BmpHeader->PixelHeight;

	ImageData = ImageBegin;
	BltBuffer = *GopBlt;
	for (Height = 0; Height < BmpHeader->PixelHeight; Height++)
	{
        // Buffer大小=長x寬
		Blt = &BltBuffer[(BmpHeader->PixelHeight-Height-1) * BmpHeader->PixelWidth];
		for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Blt++)
		{
            Blt->Blue = *ImageData++;
			Blt->Green = *ImageData++;
			Blt->Red = *ImageData++;
			/* 僅會有24位元或32位元,
            因為非者已在前面被return,若32位元則ImageData++。
            */
			switch (BmpHeader->BitPerPixel)
			{
			case 24:
				break;
			case 32:
				ImageData++;
				break;
			default:
				break;
			}
		}

		ImageIndex = (UINTN)(ImageData - ImageBegin);
        /* 除以4後,將商+餘數 */
		if ((ImageIndex % 4) != 0)
			ImageData = ImageData + (4 - (ImageIndex % 4));
	}
	
	return EFI_SUCCESS;
}    return Status;

關於Logo.bmp的顯示告一段落,接下來我們會實作Day11介紹的其他功能(輸出版號、Logo模式、時間,按B進入Boot Menu、按S進入SETUP、按ESC關機等)。在實作同時也會介紹相應知識。我們明天見!


實作Logo.bmp比我預期花更多時間,因此花了5篇篇幅(Day13-Day17)。其中Day16與Day17各提供一種可行的方法,供讀者參考。


上一篇
【Day 16】自己寫UEFI顯示自己的Logo (4/5)
下一篇
【Day 18】自己寫UEFI顯示系統時間
系列文
世界第一簡單的UEFI,實作打造自己的開機畫面31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言